﻿/***************************************************************
 * 口口
 * 点击对象管理器
 ***************************************************************/

using System;
using System.Collections.Generic;
using BitBenderGames;
using XLua;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using Yoozoo.Gameplay.Managers;
using Yoozoo.Modules.InnerCity;
using Yoozoo.Framework.Managers;
using Yoozoo.Mars.Got;
using Yoozoo.UI.YGUI;
using EventSystem = UnityEngine.EventSystems.EventSystem;

namespace Yoozoo.Manager
{
    public class TouchManager
    {
        private static TouchManager p_instance;
        public static TouchManager Ins => p_instance;

        public TouchInputController touchInputController;
        private MobileTouchCamera m_mobileTouchCamera;
        
        /// <summary>
        /// LUA函数定义
        /// </summary>
        public const string LUAFunctionName_OnTouchStart = "L_TouchManager.OnTouchStart";
        public const string LUAFunctionName_OnTouchUp = "L_TouchManager.OnTouchUp";
        public const string LUAFunctionName_On_SimpleTap = "L_TouchManager.OnSimpleTap";
        public const string LUAFunctionName_OnDragStart = "L_TouchManager.OnDragStart";
        public const string LUAFunctionName_OnDrag = "L_TouchManager.OnDrag";
        public const string LUAFunctionName_OnDragEnd = "L_TouchManager.OnDragEnd";
        public const string LUAFunctionName_OnDoubleTap = "L_TouchManager.OnDoubleTap";
        public const string LUAFunctionName_OnTouchDown = "L_TouchManager.OnTouchDown";
        public const string LUAFunctionName_OnFingerUpLastOne = "L_TouchManager.OnFingerUpLastOne";
        
        public const string LUAFunctionName_OnAITouchClick = "L_TouchManager.OnAITouchClick";

        public const string LUAFunctionName_OnScrollEnd = "L_TouchManager.OnScrollEnd";
     


        private LuaFunction luaOnTouchStart;
        private LuaFunction luaOnTouchUp;
        private LuaFunction luaOnSimpleTap;
        private LuaFunction luaOnDragStart;
        private LuaFunction luaOnDrag;
        private LuaFunction luaOnDragEnd;
        private LuaFunction luaOnDoubleClick;
        private LuaFunction luaOnFingerUpLastOne;        // 当只剩一根手指在屏幕
        
        private LuaFunction luaOnTouchDown;
        public LuaFunction luaOnAITouchClick;
        
        private LuaEnv m_LuaState;
        private LuaFunction luaOnScrollEnd;        // 滑动停止

        /// <summary>
        /// 点击事件定义
        /// </summary>
        public class TouchEvent
        {
            public Vector3 point;
            public TileCollideItem baseItem;
        }

        /// <summary>
        /// 射线目标类型
        /// </summary>
        public enum RaycastTarget
        {
            CITY_ITEM,
            CITY_GROUND
        }

        /// <summary>
        /// 点击物品事件回调
        /// </summary>
        public UnityAction<TouchEvent> OnItemTapped;
        
        /// <summary>
        /// 取消点击物品事件回调
        /// </summary>
        public UnityAction<TouchEvent> OnItemTappedCancle;

        /// <summary>
        /// 拖拽开始事件回调
        /// </summary>
        public UnityAction<TouchEvent> OnItemDragStart;

        /// <summary>
        /// 正在拖拽事件回调
        /// </summary>
        public UnityAction<TouchEvent> OnItemDrag;

        /// <summary>
        /// 拖拽结束事件回调
        /// </summary>
        public UnityAction<TouchEvent> OnItemDragStop;

        private Vector3 m_TapItemStartPos;
        private int m_LayerMaskCityItemCollider;
        private int m_LayerMaskCityGroundCollier;

        /// <summary>
        /// 开始选中的对象
        /// </summary>
        private TileCollideItem m_TapStartRaycastedItem;

        /// <summary>
        /// 选中的对象
        /// </summary>
        private TileCollideItem m_SelectedCityItem;

        /// <summary>
        /// 是否点击选中了对象
        /// </summary>
        private bool m_IsTappedCityItem;
        
        /// <summary>
        /// 是否开始拖动对象
        /// </summary>
        private bool m_IsDragItemStarted;

        /// <summary>
        /// 是否正在拖动对象
        /// </summary>
        private bool m_IsDragingItem;

        private YText textDetail;
        
        public void Initialize(MobileTouchCamera mobileTouchCamera)
        {
            p_instance = this;

            m_mobileTouchCamera = mobileTouchCamera;
            touchInputController = m_mobileTouchCamera.TouchInputController;

            m_LuaState = LuaManager.mainState;
            if (m_LuaState == null)
            {
                throw new Exception("LuaManager is null");
            }
            luaOnTouchStart = m_LuaState.Global.GetInPath<LuaFunction>(LUAFunctionName_OnTouchStart);
            luaOnTouchUp = m_LuaState.Global.GetInPath<LuaFunction>(LUAFunctionName_OnTouchUp);
            luaOnSimpleTap = m_LuaState.Global.GetInPath<LuaFunction>(LUAFunctionName_On_SimpleTap);
            luaOnDragStart =  m_LuaState.Global.GetInPath<LuaFunction>(LUAFunctionName_OnDragStart);
            luaOnDrag = m_LuaState.Global.GetInPath<LuaFunction>(LUAFunctionName_OnDrag);
            luaOnDragEnd = m_LuaState.Global.GetInPath<LuaFunction>(LUAFunctionName_OnDragEnd);
            luaOnDoubleClick = m_LuaState.Global.GetInPath<LuaFunction>(LUAFunctionName_OnDoubleTap); 
            luaOnTouchDown = m_LuaState.Global.GetInPath<LuaFunction>(LUAFunctionName_OnTouchDown);
            luaOnFingerUpLastOne = m_LuaState.Global.GetInPath<LuaFunction>(LUAFunctionName_OnFingerUpLastOne);
            
            luaOnAITouchClick = m_LuaState.Global.GetInPath<LuaFunction>(LUAFunctionName_OnAITouchClick);
            luaOnScrollEnd = m_LuaState.Global.GetInPath<LuaFunction>(LUAFunctionName_OnScrollEnd);

            m_LayerMaskCityItemCollider = LayerMask.GetMask("city");
            m_LayerMaskCityGroundCollier = LayerMask.GetMask("cityground");


            touchInputController.OnInputClick += On_TouchClick;
            touchInputController.OnFingerUp += On_TouchUp;
            touchInputController.OnFingerDown += On_TouchStart;
            touchInputController.OnTouchDown += On_TouchDown;
            touchInputController.OnDragStart += On_DragStart;
            touchInputController.OnDragUpdate += On_Drag;
            touchInputController.OnDragStop += On_DragEnd;

            touchInputController.OnFingerUpLastOne += On_FingerUpLastOne;
            touchInputController.OnScrollEnd += On_ScrollEnd;
        }

        public void Destroy()
        {
            touchInputController.OnInputClick -= On_TouchClick;
            touchInputController.OnFingerUp -= On_TouchUp;
            touchInputController.OnFingerDown -= On_TouchStart;
            touchInputController.OnTouchDown -= On_TouchDown;
            touchInputController.OnDragStart -= On_DragStart;
            touchInputController.OnDragUpdate -= On_Drag;
            touchInputController.OnDragStop -= On_DragEnd;

            touchInputController.OnFingerUpLastOne -= On_FingerUpLastOne;
            touchInputController.OnScrollEnd -= On_ScrollEnd;

        }

        #region 触摸事件处理

        
        
        private bool GetRayCast(Vector3 clickPosition, out RaycastHit hitInfo)
        {
            Ray camRay = m_mobileTouchCamera.Cam.ScreenPointToRay(clickPosition);
            if (Physics.Raycast(camRay, out hitInfo))
            {
                return true;
            }
            return false;
        }

        private RaycastHit[] GetRayCastAll(Vector3 clickPosition)
        {
            Ray camRay = m_mobileTouchCamera.Cam.ScreenPointToRay(clickPosition);
            var all = Physics.RaycastAll(camRay);
            return all;
        }

        private void On_FingerUpLastOne(Vector3 fingerPos, bool isonui)
        {
            RaycastHit hitInfo;
            GetRayCast(fingerPos, out hitInfo);
            luaOnFingerUpLastOne.Call(fingerPos, hitInfo);
        }


        private void On_TouchClick(Vector3 clickPosition, bool isdoubleclick, bool islongtap,bool isOnUI)
        {
            bool isSelectedUi = TouchInputController.mLastSelectedUi != null;
            
            RaycastHit hitInfo;
            GetRayCast(clickPosition, out hitInfo);
            var allHitInfo = GetRayCastAll(clickPosition);
            if (isdoubleclick)
            {
                //CityDisplayController.GetInstance().OnTouchDoubleClick(hitInfo,isOnUI);
                luaOnDoubleClick.Call(clickPosition,hitInfo,isOnUI,isSelectedUi,islongtap,allHitInfo);
            }
            else
            {
                //CityDisplayController.GetInstance().OnTouchClick(hitInfo,isOnUI);
                luaOnSimpleTap.Call(clickPosition, hitInfo,isOnUI,isSelectedUi,islongtap, allHitInfo);
            }
        }

        private void On_TouchUp()
        {
            luaOnTouchUp.Call();
        }
        
        
        private void On_TouchStart(Vector3 clickPosition,bool isOnUI)
        {
            //
            RaycastHit[] hitInfos = GetRayCastAll(clickPosition);
            if (hitInfos.Length > 0)
            {
                luaOnTouchStart.Call(clickPosition, hitInfos[0], isOnUI, hitInfos);
            }
            else
            {
                luaOnTouchStart.Call(clickPosition, default(RaycastHit), isOnUI, hitInfos);
            }
        }
        
        private void On_TouchDown(float holdTime,bool isOnUI)
        {
            luaOnTouchDown.Call(holdTime,isOnUI);
        }

        public void On_ScrollEnd()
        {
            luaOnScrollEnd.Call();
        }

        private void On_DragEnd(Vector3 dragstoppos, Vector3 dragfinalmomentum)
        {
            RaycastHit hitInfo;
            GetRayCast(dragstoppos, out hitInfo);
            luaOnDragEnd.Call(dragstoppos, hitInfo);
        }

        private void On_Drag(Vector3 dragposstart, Vector3 dragposcurrent, Vector3 correctionoffset, bool isonui)
        {
            RaycastHit hitInfo = default;
            var allHitInfo = GetRayCastAll(dragposcurrent);
            if (allHitInfo!=null && allHitInfo.Length > 0 )
            {
                luaOnDrag.Call(dragposcurrent, allHitInfo[0],allHitInfo);
            }
            else
            {
                luaOnDrag.Call(dragposcurrent,hitInfo);
            }    
        }

        private void On_DragStart(Vector3 pos, bool islongtap,bool isOnUI)
        {
            RaycastHit hitInfo;
            GetRayCast(pos, out hitInfo);
            luaOnDragStart.Call(pos, hitInfo, isOnUI);
        }


        #endregion

        private TileCollideItem TryGetRaycastHitItem(Vector3 touch)
        {
            RaycastHit hit;
            if (TryGetRaycastHit(touch, out hit, RaycastTarget.CITY_ITEM))
            {
                return hit.collider.gameObject.GetComponent<TileCollideItem>();
            }

            return null;
        }

        private Vector3 TryGetRaycastHitGround(Vector3 touch)
        {
            RaycastHit hit;
            if (TryGetRaycastHit(touch, out hit, RaycastTarget.CITY_GROUND))
            {
                return hit.point;
            }

            return Vector3.positiveInfinity;
        }

        private bool TryGetRaycastHit(Vector3 touch, out RaycastHit hit, RaycastTarget target)
        {
            Ray ray = WorldCameraManager.mainCamera.ScreenPointToRay(touch);
            int layerMask = 0;
            switch (target)
            {
                case RaycastTarget.CITY_ITEM:
                    layerMask = m_LayerMaskCityItemCollider;
                    break;
                case RaycastTarget.CITY_GROUND:
                    layerMask = m_LayerMaskCityGroundCollier;
                    break;
            }
            
            return Physics.Raycast(ray, out hit, 1000, 1 << m_LayerMaskCityItemCollider | 1 << m_LayerMaskCityGroundCollier);
        }
    }
}